<?php

namespace App;

use lib\App\AppException;
use lib\Server\Http\Response;

class App
{
	public static $base_namespace;

	static public function run($http)
	{
		try {
			self::setRouter();
			$handler_result = self::handler($http);
			if (false === $handler_result) {
				#处理部分错误
				$http->response->setStatusCode(401);
				return $http->response->withJson([
					'error_code' => 401,
					'error_message' => 'Unauthorized access',
					'server_version' => VERSION,
				]);
			}
			else {
				if (!($handler_result instanceof Response) && $http->response->bodyIsNull()) {
					return $http->response->with($handler_result);
				}
			}
		} catch (AppException $_error) {
			#错误返回
			return $http->response->withJson([
				'error_code' => $_error->getCode(),
				'error_message' => $_error->getMessage()
			]);
		} catch (\Exception  $e) {
			#系统异常
			error_log($e);
			return $http->response->withJson([
				'error_code' => 500,
				'error_message' => '内部故障'
			]);
		}

	}

	static public function setRouter()
	{
		$routes = include ROOT_DIR . DIRECTORY_SEPARATOR . 'app/router.php';
		foreach ($routes as $key => $val) {
			\Router::addRoute($key, $val);
		}
	}

	static public function handler($http)
	{
		if(null == $http->base_namespace){
			$http->base_namespace = 'app';
		}

//		if (strtolower($http->request->method) === 'options') {
//			$http->response->setHeader('Access-Control-Allow-Origin', '*');
//			$http->response->setHeader('Access-Control-Allow-Headers', 'content-type');
//
//			return $http->response->withJson([
//				'error_code' => 0,
//				'message' => 'Allow'
//			]);
//		}

		$controller = \Router::getController($http->request);
		if (!$controller && !is_array($controller)) {
			return false;
		}

		foreach ($controller as $key => $value) {
			if (!$value) {
				unset($controller[$key]);
			}
		}

		$action = $controller['action'];

		unset($controller['action']);
		if (isset($controller['middleware'])) {
			$middleware = $controller['middleware'];
			unset($controller['middleware']);
		}

		$class = $http->base_namespace.'\\'.join('\\', $controller);

		if (!class_exists($class, true)) {
			throw new AppException("{$class} not found", 500);
		}
		else {
			if (method_exists($class, $action)) {
				if (isset($middleware)) {
					$middlewareClass = $http->base_namespace."\\$middleware";
					if (!class_exists($middlewareClass)) {
						throw new AppException("Middleware:{$middlewareClass} not found", 500);
					}
					elseif (!method_exists($middlewareClass, 'handler')) {
						throw new AppException("Middleware:{$middlewareClass} action handler not found", 500);
					}
					else {
						return (new $middlewareClass($http->request, $http->response))
							->handler($controller, function () use ($http, $class, $action) {
								return (new $class($http))->$action();
							});
					}
				}
				else {
					return (new $class($http))->$action();
				}
			}
			else {
				throw new AppException("{$class} not found action:{$action}", 500);
			}
		}

	}

}